package com.cmy.common.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileReader;
import org.springframework.core.io.ClassPathResource;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

/**
 * @Author:Cmy
 * @Date:2022/11/25-9:14
 * @Description:
 */
public class MyFileUtil {

    /**
     * 根据 文件名获取resource inputStream
     * @param fileName
     * @return
     */
    public static InputStream readFileForJar(String fileName){
        ClassPathResource resource = new ClassPathResource(fileName);
        InputStream inputStream = null;
        try {
            return resource.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * Channel的零拷贝 对于to 如果路径不存在会自动创建父级目录
     * @param from
     * @param to
     * @return
     */
    public static boolean transferTo(String from, String to){
        boolean success = false;
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            createIfTheParentNotExists(to);
            fis = new FileInputStream(from);
            fos = new FileOutputStream(to);
            FileChannel fromChannel = fis.getChannel();
            FileChannel toChannel = fos.getChannel();
            ////效率 更高 底层利用了操作系统的零拷贝 进行优化
            //fromChannel.transferTo(0,fromChannel.size(),toChannel);
            //transferTo传输数据存在上限大小限制为2G 可用如下方式多次传输
            long size = fromChannel.size();
            //left 变量表示还剩下多少字节没有传输
            for (long left = size;left>0;){
                long actualNumberOfBytes = fromChannel.transferTo(size-left, left, toChannel);
                left = left - actualNumberOfBytes;
            }
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (from!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (to!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return success;
    }

    /**
     * 文件拷贝 如果路径不存在会自动创建父级目录
     * @return
     */
    public static boolean copyFile(String sourcePath,String targetPath){
        boolean success = false;
        Path source = Paths.get(sourcePath);
        Path target = Paths.get(targetPath);
        createIfTheParentNotExists(targetPath);
        try {
            Files.copy(source,target);
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 文件移动 如果路径不存在会自动创建父级目录
     */
    public static boolean mvFile(String sourcePath,String targetPath){
        boolean success = false;
        Path source = Paths.get(sourcePath);
        Path target = Paths.get(targetPath);
        createIfTheParentNotExists(targetPath);
        try {
            Files.move(source,target,StandardCopyOption.ATOMIC_MOVE);
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 文件删除
     */
    public static boolean deleteFile(String targetPath){
        boolean success = false;
        Path target = Paths.get(targetPath);
        try {
            success = Files.deleteIfExists(target);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 删除非空文件夹
     * @return
     */
    public static boolean deleteNotEmptyFile(String targetPath){

        boolean success = false;
        Path deleteStart = Paths.get(targetPath);
        try {
            Files.walkFileTree(deleteStart,new SimpleFileVisitor<Path>(){
                //先删除文件
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    Files.deleteIfExists(file);
                    //System.out.println("del file:["+file+"] ===> "+success);
                    return super.visitFile(file, attrs);
                }

                //再删文件夹
                @Override
                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
                    Files.deleteIfExists(dir);
                    //System.out.println("del dir:{"+dir+"} ===> "+success );
                    return super.postVisitDirectory(dir, exc);
                }
            });
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 全量拷贝目标文件夹
     */
    public static boolean copyTheTargetFolderInFull(String source,String target){
        boolean success = false;
        try {
            Files.walk(Paths.get(source)).forEach(path -> {
                try {
                    String targetName = path.toString().replace(source,target);
                    if (Files.isDirectory(path)) {//目录
                        Files.createDirectory(Paths.get(targetName));
                    }
                    // 是否是文件
                    else if (Files.isRegularFile(path)){
                        Files.copy(path,Paths.get(targetName));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            });
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 如果路径不存在会自动创建父级目录
     * @param targetPath
     */
    public static void createIfTheParentNotExists(String targetPath){
        Path path = Paths.get(targetPath);
        Path parent = path.getParent();//父级目录
        if (Files.notExists(path)){
            try {
                Files.createDirectories(parent);//不存在则创建父级目录
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

    